package edu.udo.sopra10.chaturaji.entities.pieces;

import static edu.udo.sopra10.chaturaji.util.ExceptionUtil.assertNotNull;
import static java.util.Collections.emptyList;

import java.util.ArrayList;
import java.util.Collection;

import edu.udo.sopra10.chaturaji.entities.Player;
import edu.udo.sopra10.chaturaji.entities.Square;
import edu.udo.sopra10.chaturaji.entities.coordinates.Movement;
import edu.udo.sopra10.chaturaji.entities.coordinates.Position;
import edu.udo.sopra10.chaturaji.util.CloneUtil;

/**
 * A piece that can "jump" over other pieces. It must fulfill the following
 * contract:
 * <ul>
 * <li>It can move to arbitrary squares without a line of movement</li>
 * <li>It can capture other pieces if and only if it moves onto their square</li>
 * </ul>
 * 
 * @author Simon Dierl
 */
abstract class JumpingPiece extends Piece {

	/**
	 * The movements this piece is capable of.
	 */
	private final Collection<Movement> basicMovements;

	/**
	 * Create a new piece with certain basic movements.
	 * 
	 * @param basicMovements
	 *            all movements this piece is theoretically capable of. Must
	 *            neither be {@code null} nor contain {@code null}.
	 * @param score
	 *            the score awarded to a player capturing this piece. Must be
	 *            {@code >= 0}.
	 * @param owner
	 *            the piece's owner, must not be {@code null}.
	 * @param square
	 *            the square this piece is standing on. May be {@code null} to
	 *            indicate a captured piece.
	 */
	protected JumpingPiece(final Collection<Movement> basicMovements,
			final byte score, final Player owner, final Square square) {
		super(score, owner, square);
		this.basicMovements = basicMovements;
	}

	@Override
	public Actions getPossibleActions(final Square[][] board,
			final Position currentPosition) {
		assertNotNull(board, "board");
		assertNotNull(currentPosition, "currentPosition");

		final Collection<Position> possibleMoves = new ArrayList<Position>(
				basicMovements.size());
		final Collection<Position> possibleCaptures = new ArrayList<Position>(
				basicMovements.size());
		final Collection<Position> possiblePawnPromotions = emptyList();

		for (final Movement basicMovement : basicMovements) {
			final Position movePosition = CloneUtil.clone(currentPosition);
			try {
				movePosition.shift(basicMovement);
			} catch (final IllegalArgumentException e) {
				continue;
			}

			final Piece piece = board[movePosition.getX()][movePosition.getY()]
					.getPiece();
			if (piece == null) {
				possibleMoves.add(movePosition);
			} else if (!piece.getOwner().equals(owner)) {
				possibleCaptures.add(movePosition);
			}
		}

		return (new Actions(possibleMoves, possibleCaptures, null,
				possiblePawnPromotions));
	}
}
